package com.jdls.tanhua.server;

import cn.hutool.core.collection.CollUtil;
import com.jdls.tanhua.dubbo.*;
import com.jdls.tanhua.enums.CommentType;
import com.jdls.tanhua.exception.AllException;
import com.jdls.tanhua.interceptor.UserHolder;
import com.jdls.tanhua.mongo.*;
import com.jdls.tanhua.pojo.UserInfo;
import com.jdls.tanhua.template.OssTemplate;
import com.jdls.tanhua.vo.*;
import io.netty.util.internal.StringUtil;
import org.apache.dubbo.config.Constants;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.lang.reflect.Array;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author 嘉德罗斯
 * @date 2021/10/27
 */
@Service
public class MovementsServer {

    @Autowired
    private RedisTemplate<String ,String> redisTemplate;

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private VisitorsApi visitorsApi;

    @DubboReference
    private FriendApi friendApi;

    @DubboReference
    private CommentApi commentApi;

    @DubboReference
    private MovementTimeLineApi movementTimeLineApi;

    public void save(Movement movement, MultipartFile[] multipartFiles) throws IOException {

        if (movement.getTextContent() == null) {
            throw new AllException(ErrorResult.txtErr());
        }
        List<String> list = new ArrayList<>();
        for (MultipartFile multipartFile : multipartFiles) {
            String oss = "https://" + ossTemplate.oss(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            list.add(oss);
        }
        movement.setMedias(list);
        Long userId = UserHolder.getUserId();
        System.out.println(movement);
        movement.setUserId(userId);
        movement = movementApi.save(movement);
        List<Friend> friends = movementApi.findOne(movement);
        movementTimeLineApi.save(movement.getId(), friends);
    }

    public PageResult all(Long userId, Integer page, Integer pagesize) {

        PageResult pageResult = new PageResult();
        UserInfo userInfo = userInfoApi.find(userId);
        List<Movement> movements = movementApi.findAll(userId, page, pagesize);
        List<MovementsVo> movementsVos = new ArrayList<>();
        for (Movement movement : movements) {
            MovementsVo init = MovementsVo.init(userInfo, movement);
            movementsVos.add(init);
        }
        pageResult.setPage(page);
        pageResult.setPageSize(pagesize);
        pageResult.setItems(movementsVos);
        pageResult.setCounts(movementsVos.size());
        Integer pages = movementsVos.size() % pagesize == 0 ? movementsVos.size() / pagesize : movementsVos.size() / pagesize + 1;
        pageResult.setPages(pages);
        return pageResult;
    }

    public PageResult Friend(Integer page, Integer pagesize) {
        Long userId = UserHolder.getUserId();

        PageResult result = new PageResult();
        List<Friend> friends = friendApi.findAll(userId);
        if (friends == null || friends.size() == 0) {
            return result;
        }
        List<Long> ids = new ArrayList<>();
        for (Friend friend : friends) {
            ids.add(friend.getFriendId());
        }

        List<MovementTimeLine> movementTimeLines = movementTimeLineApi.findAll(ids, userId);
        if (movementTimeLines == null || movementTimeLines.size() == 0) {
            return result;
        }
        List<ObjectId> movementIds = new ArrayList<>();
        for (MovementTimeLine movementTimeLine : movementTimeLines) {
            movementIds.add(movementTimeLine.getMovementId());
        }

        List<Movement> movements = movementApi.findAll(movementIds, page, pagesize);
        List<Long> friendIds = new ArrayList<>();
        for (Movement movement : movements) {
            friendIds.add(movement.getUserId());
        }


        List<UserInfo> userInfos = userInfoApi.findAll(friendIds);
        List<MovementsVo> items = publish(userInfos, movements,userId);
        PageResult pageResult = new PageResult(page, pagesize, items.size(), items);
        return pageResult;
    }

    //查询推荐id
    public PageResult randomFind(Integer page, Integer pagesize) {

        Long userId = UserHolder.getUserId();

        List<RecommendUser> recommendUsers = recommendUserApi.findAll(userId);

        if (recommendUsers == null || recommendUsers.size() == 0) {
            return null;
        }
        List<Long> ids = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUsers) {
            ids.add(recommendUser.getUserId());
        }


        List<Movement> all = movementApi.findMovement(ids, page, pagesize);

        List<Long> userIds = new ArrayList<>();
        for (Movement movement : all) {
            userIds.add(movement.getUserId());
        }


        List<UserInfo> userInfos = userInfoApi.findUserInfos(userIds);

        List<MovementsVo> items = publish(userInfos, all,userId);

        PageResult pageResult = new PageResult(page, pagesize, items.size(), items);
        return pageResult;
    }

    //查询好友动态和推荐动态公共方法
    public List<MovementsVo> publish(List<UserInfo> userInfos, List<Movement> all,Long id) {

        List<MovementsVo> items = new ArrayList<>();
        for (Movement movement : all) {
            for (UserInfo userInfo : userInfos) {
                if (movement.getUserId() == userInfo.getId()) {
                    MovementsVo init = MovementsVo.init(userInfo, movement);
                    //主key
                    String key =  movement.getId().toHexString();
                    //点赞key
                    String likeKey = CommentType.LIKE.getType()+"_"+id;
                    //判断点赞key是否存在
                    if (redisTemplate.opsForHash().hasKey(key,likeKey)){
                        init.setHasLiked(1);
                    }
                    //判断喜欢key是否存在
                    String loveKey = CommentType.LOVE.getType()+"_"+id;
                    if (redisTemplate.opsForHash().hasKey(key,loveKey)){
                        init.setHasLoved(1);
                    }
                    items.add(init);
                    break;
                }
            }
        }
        return items;
    }

    //根据动态id查单条动态
    public MovementsVo findOne(ObjectId id) {
        //根据动态id查询动态表获取当前动态的数据
        Movement movement  = movementApi.findOne(id);
        //从当前动态数据里面获取发布这条动态用户的id
        Long userId = movement.getUserId();
        //根据用户id查询当前用户的基本信息
        UserInfo userInfo = userInfoApi.find(userId);
        //使用vo里的有参构造封装
        MovementsVo movementsVo = MovementsVo.init(userInfo, movement);
        //返回vo对象
        return movementsVo;
    }

    //动态点赞
    public Integer likeCount(String id) {
        //当前用户id
        Long userId = UserHolder.getUserId();
        //当前动态id
        ObjectId movementId = new ObjectId(id);
        //互动类型
        int like = CommentType.LIKE.getType();

        //判断当前用户是否点赞
        Comment comment = commentApi.find(userId,movementId,like);
        if(comment != null){
            throw new AllException(ErrorResult.likeErr());
        }
        //未点赞则保存一条数据
        comment = new Comment();
        comment.setPublishId(movementId);
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(userId);
        comment.setCreated(System.currentTimeMillis());
        Integer likeCount = commentApi.save(comment);

        //主key
        String key =  id;
        //hashKey
        String hashKey = CommentType.LIKE.getType()+"_"+userId;

        redisTemplate.opsForHash().put(key,hashKey,"1");
        return likeCount;
    }

    //取消点赞
    public Integer disLikeCount(String id) {
        //当前用户id
        Long userId = UserHolder.getUserId();
        //当前动态id
        ObjectId movementId = new ObjectId(id);
        //互动类型
        int like = CommentType.LIKE.getType();
        //判断当前用户是否点赞
        Comment comment = commentApi.find(userId,movementId,like);
        if(comment == null){
            //如果不存在就是未点赞
            throw new AllException(ErrorResult.dislikeErr());
        }
        //目前最新的数据
        Integer count = commentApi.delete(userId, movementId, like);

        //主key
        String key =  id;
        //hashKey
        String hashKey = CommentType.LIKE.getType()+"_"+userId;

        redisTemplate.opsForHash().delete(key,hashKey);
        return count;
    }

    //动态喜欢
    public Integer loveCount(String id) {
        //当前用户id
        Long userId = UserHolder.getUserId();
        //当前动态id
        ObjectId movementId = new ObjectId(id);
        //互动类型
        int love = CommentType.LOVE.getType();

        //判断当前用户是否点赞
        Comment comment = commentApi.find(userId,movementId,love);
        if(comment != null){
            throw new AllException(ErrorResult.loveErr());
        }
        //未喜欢则保存一条数据
        comment = new Comment();
        comment.setPublishId(movementId);
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(userId);
        comment.setCreated(System.currentTimeMillis());
        Integer likeCount = commentApi.save(comment);

        //主key
        String key =  id;
        //hashKey
        String hashKey = CommentType.LOVE.getType()+"_"+userId;

        redisTemplate.opsForHash().put(key,hashKey,"1");
        return likeCount;
    }

    //取消喜欢
    public Integer disLoveCount(String id) {
        //当前用户id
        Long userId = UserHolder.getUserId();
        //当前动态id
        ObjectId movementId = new ObjectId(id);
        //互动类型
        int love = CommentType.LOVE.getType();
        //判断当前用户是否点赞
        Comment comment = commentApi.find(userId,movementId,love);
        if(comment == null){
            //如果不存在就是未点赞
            throw new AllException(ErrorResult.disLoveErr());
        }
        //目前最新的数据
        Integer count = commentApi.delete(userId, movementId, love);

        //主key
        String key =  id;
        //hashKey
        String hashKey = CommentType.LOVE.getType()+"_"+userId;

        redisTemplate.opsForHash().delete(key,hashKey);
        return count;

    }

    //谁看过我
    public List<FateValueVo> visitors() {
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String key = "visitors"+format;
        Long userId = UserHolder.getUserId();
        String hashKey = userId.toString();
        String value = (String) redisTemplate.opsForHash().get(key, hashKey);
        Long date = value == null ? null : Long.valueOf(value);

        //获取当天第一次看过我的所有用户id
        List<Visitors> visitors = visitorsApi.findByIds(date,userId,format);
        List<Long> ids = CollUtil.getFieldValues(visitors, "visitorUserId", Long.class);

        //根据用户id查询这些用户的基本信息
        List<UserInfo> userInfos = userInfoApi.findAll(ids);

        //构造vo
        List<FateValueVo> fateValueVos = new ArrayList<>();
        for (Visitors visitor : visitors) {
            for (UserInfo userInfo : userInfos) {
                if (visitor.getVisitorUserId() == userInfo.getId()){
                    FateValueVo fateValueVo = new FateValueVo();
                    fateValueVo.setAge(Integer.valueOf(userInfo.getAge()));
                    fateValueVo.setAvatar(userInfo.getAvatar());
                    String score = visitor.getScore().toString();
                    int i = score.indexOf(".");
                    fateValueVo.setFateValue(Integer.valueOf(score.substring(0,i)));
                    fateValueVo.setGender(userInfo.getGender());
                    fateValueVo.setId(Math.toIntExact(userInfo.getId()));
                    fateValueVo.setNickname(userInfo.getNickname());
                    String[] split = userInfo.getTags().split(",");
                    fateValueVo.setTags(split);
                    fateValueVos.add(fateValueVo);
                }
            }
        }
        return fateValueVos;
    }
}
